﻿using Clancy.Common;
using Clancy.Interfaces;
using ReactiveUI;
using System;
using System.Reactive.Subjects;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Clancy.Ui.ViewModels
{
    public class MonitorViewModel : ReactiveObject, IObserver<ISurveilanceResultFrame>
    {
        protected SolidColorBrush AlarmBackgroundColor;
        protected SolidColorBrush DefaultBackgroundColor;
        private readonly BehaviorSubject<ISurveilanceResultFrame> m_CurrentFrameObservable = new BehaviorSubject<ISurveilanceResultFrame>(null);
        private readonly ISurveilanceObject m_SurveilanceObject;
        private readonly ObservableAsPropertyHelper<ISurveilanceResultFrame> m_SurveilanceResultFrameHelper;
        private SolidColorBrush RecordingBackgroundColor;

        public MonitorViewModel(ISurveilanceObject surveilanceObject)
        {
            m_SurveilanceObject = surveilanceObject;

            DefaultBackgroundColor = new SolidColorBrush(Color.FromRgb(0x8F, 0x8F, 0x8F));
            AlarmBackgroundColor = new SolidColorBrush(Color.FromRgb(0xFF, 0x2F, 0x5F));
            RecordingBackgroundColor = new SolidColorBrush(Color.FromRgb(0xFF, 0x9F, 0x5F));

            m_SurveilanceResultFrameHelper = new ObservableAsPropertyHelper<ISurveilanceResultFrame>(m_CurrentFrameObservable, _ =>
            {
                this.RaisePropertyChanged("CurrentFrame");
                this.RaisePropertyChanged("FrameDifference");
                this.RaisePropertyChanged("FramesPerSecond");
                this.RaisePropertyChanged("BackgroundColor");
            });

            m_SurveilanceObject.ObservableForProperty(prop => prop.Threshold).Subscribe(_ => this.RaisePropertyChanged("Threshold"));

            InitCommands();
        }

        public Brush BackgroundColor
        {
            get
            {
                if (m_SurveilanceResultFrameHelper.Value == null)
                    return DefaultBackgroundColor;

                if (m_SurveilanceResultFrameHelper.Value.AlarmTriggered)
                {
                    return AlarmBackgroundColor;
                }
                if (m_SurveilanceResultFrameHelper.Value.Recording)
                {
                    return RecordingBackgroundColor;
                }
                return DefaultBackgroundColor;
            }
        }

        public ReactiveCommand<object> CmdShowAdvanceProperties { get; private set; }

        public BitmapSource CurrentFrame
        {
            get
            {
                if ((m_SurveilanceResultFrameHelper.Value == null) ||
                    (m_SurveilanceResultFrameHelper.Value.Frame == null))
                    return null;

                return m_SurveilanceResultFrameHelper.Value.Frame.ToBitmapSource();
            }
        }

        public virtual double FrameDifference
        {
            get
            {
                if ((m_SurveilanceResultFrameHelper.Value == null) ||
                    (m_SurveilanceResultFrameHelper.Value.Frame == null))
                    return 0;

                return m_SurveilanceResultFrameHelper.Value.FrameDifference;
            }
        }

        public virtual double FramesPerSecond
        {
            get
            {
                if ((m_SurveilanceResultFrameHelper.Value == null) ||
                    (m_SurveilanceResultFrameHelper.Value.Frame == null))
                    return 0;

                return m_SurveilanceResultFrameHelper.Value.FramesPerSecond;
            }
        }

        public ISurveilanceObject SurveilanceObject
        {
            get { return m_SurveilanceObject; }
        }

        public virtual int Threshold
        {
            get
            {
                if (m_SurveilanceObject == null)
                    return 0;
                return m_SurveilanceObject.Threshold;
            }
        }

        public void OnCompleted()
        {
            throw new NotImplementedException();
        }

        public void OnError(Exception error)
        {
            throw new NotImplementedException();
        }

        public void OnNext(ISurveilanceResultFrame value)
        {
            if ((value == null) || (value.Frame == null))
                return;
            m_CurrentFrameObservable.OnNext(value);
        }

        private void InitCommands()
        {
            CmdShowAdvanceProperties = ReactiveCommand.Create();
            CmdShowAdvanceProperties.Subscribe(_ => ShowAdvanceProperties());
        }

        private void ShowAdvanceProperties()
        {
            throw new NotImplementedException();
        }
    }
}